package com.dqx.opengl_es_demo.camera;

import android.content.Context;
import android.graphics.SurfaceTexture;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;

import com.dqx.opengl_es_demo.R;
import com.dqx.utils.CameraUtils;
import com.dqx.utils.GLUtils;

import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

/**
 * 摄像头渲染器
 */
public class CameraRenderer implements GLSurfaceView.Renderer {
    //上下文
    Context context;
    //纹理处理控件
    private SurfaceTexture mSurfaceTexture;
    //摄像头id。0:后置，1:前置
    private int cameraId = 0;
    //顶点坐标缓冲区
    private FloatBuffer mPosBuffer;
    //纹理坐标缓冲区
    private FloatBuffer mTexBuffer;
    //顶点坐标矩阵
    private float[] mPosCoordinate = {
            -1.0f, -1.0f,
            -1.0f, 1.0f,
            1.0f, -1.0f,
            1.0f, 1.0f
    };
    //前置摄像头对应的纹理坐标
    private float[] mTexCoordinateForntRight = {
            0.0f, 1.0f,
            1.0f, 1.0f,
            0.0f, 0.0f,
            1.0f, 0.0f
    };
    //后置摄像头对应的纹理坐标
    private float[] mTexCoordinateBackRight = {
            1.0f, 1.0f,
            0.0f, 1.0f,
            1.0f, 0.0f,
            0.0f, 0.0f
    };
    //程序对象
    public int mProgram;
    //“顶点坐标”属性句柄
    private int uPosHandle;
    //“纹理坐标”属性句柄
    private int aTexHandle;
    //“变换矩阵”属性句柄
    private int mMVPMatrixHandle;
    //投影矩阵
    private float[] mProjectMatrix = new float[16];
    //相机矩阵
    private float[] mCameraMatrix = new float[16];
    //最终变化矩阵
    private float[] mMVPMatrix = new float[16];

    //摄像头工具类
    CameraUtils camera;

    public CameraRenderer(Context context) {
        this.context = context;
        camera = new CameraUtils();
        mPosBuffer = GLUtils.convertToFloatBuffer(mPosCoordinate);
        if (cameraId == 0) {
            mTexBuffer = GLUtils.convertToFloatBuffer(mTexCoordinateBackRight);
        } else {
            mTexBuffer = GLUtils.convertToFloatBuffer(mTexCoordinateForntRight);
        }
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        //设置背景色
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

        //创建着色器程序
        mProgram = GLUtils.buildProgram(context, R.raw.vertex_camera, R.raw.fragment_camera);
        //获取顶点着色器position属性的句柄
        uPosHandle = GLES20.glGetAttribLocation(mProgram, "position");
        //获取顶点着色器inputTextureCoordinate属性的句柄
        aTexHandle = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate");
        //获取顶点着色器textureTransform属性的句柄
        mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "textureTransform");

        //初始化纹理处理控件
        mSurfaceTexture = new SurfaceTexture(createTexture());
        //打开摄像头
        camera.open(cameraId);
        //设置预览控件
        camera.setPreviewTexture(mSurfaceTexture);
        //开始预览
        camera.preview();
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        //设置视图窗口的位置和大小
        GLES20.glViewport(0, 0, width, height);

        //宽高比
        float ratio = (float) width / height;
        //设置正交投影矩阵
        Matrix.frustumM(mProjectMatrix, 0, -1, 1, -ratio, ratio, 1, 7);
        //设置相机矩阵
        Matrix.setLookAtM(mCameraMatrix, 0, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
        //计算得到变换矩阵
        Matrix.multiplyMM(mMVPMatrix, 0, mProjectMatrix, 0, mCameraMatrix, 0);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        if (mSurfaceTexture != null) {
            //清除深度缓冲与颜色缓冲
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
            //将纹理更新为最新的图像数据
            mSurfaceTexture.updateTexImage();

            //使用程序
            GLES20.glUseProgram(mProgram);
            //启用顶点坐标属性句柄
            GLES20.glEnableVertexAttribArray(uPosHandle);
            //启用纹理坐标属性句柄
            GLES20.glEnableVertexAttribArray(aTexHandle);
            //设置顶点坐标数据
            GLES20.glVertexAttribPointer(uPosHandle, 2, GLES20.GL_FLOAT, false, 0, mPosBuffer);
            //设置纹理坐标数据
            GLES20.glVertexAttribPointer(aTexHandle, 2, GLES20.GL_FLOAT, false, 0, mTexBuffer);
            //设置变换矩阵数据
            GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
            //绘制
            GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, mPosCoordinate.length / 2);
        }
    }

    /**
     * 创建纹理对象，并返回纹理对象的id
     *
     * @return
     */
    public int createTexture() {
        //创建数组来装载纹理id
        int[] tex = new int[1];
        //创建一个空的纹理对象
        GLES20.glGenTextures(1, tex, 0);
        //将此纹理对象绑定到OES纹理单元上
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]);
        //设置纹理过滤参数
        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
                GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
                GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
                GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
                GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
        return tex[0];
    }
}